package org.whuims.service.document;

import org.apache.shiro.SecurityUtils;
import org.elasticsearch.common.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.Criteria;
import org.springframework.data.solr.core.query.Query;
import org.springframework.data.solr.core.query.SimpleQuery;
import org.springframework.data.solr.core.query.result.ScoredPage;
import org.springframework.stereotype.Service;
import org.whuims.entity.Document;
import org.whuims.entity.vo.DocumentVo;
import org.whuims.repository.solr.SolrDocumentDao;
import org.whuims.service.account.ShiroDbRealm;

import java.text.ParseException;
import java.util.Date;
import java.util.List;

/**
 * Created by zhongwei on 16/12/22.
 */
@Service
public class DocumentSolrService {

    @Autowired
    private SolrDocumentDao solrDocumentDao;
    @Autowired
    private SolrTemplate solrTemplate;

    public Page<Document> findBySearchFields(Pageable pageable, String searchFields) {
        return solrDocumentDao.findBySearchFields(pageable, searchFields);
    }

    public Page<Document> findByTemplate(Pageable pageable, String keyword) {
        Query query = new SimpleQuery();
        query.setPageRequest(pageable);
        query.addCriteria(new Criteria("searchFields").expression(keyword));
        if (!getCurrentUserName().toLowerCase().equals("admin")) {
            query.addCriteria(new Criteria("userId").expression(String.valueOf(getCurrentUserId())));
        }
        solrTemplate.setSolrCore("docs_document");
        ScoredPage<Document> scoredPage = solrTemplate.queryForPage(query, Document.class);
        return scoredPage;
    }

    public Page<Document> findByTemplate(Pageable pageable, DocumentVo documentVo) {
        Query query = null;
        try {
            query = buildQuery(documentVo);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (!getCurrentUserName().toLowerCase().equals("admin")) {
            query.addCriteria(new Criteria("userId").expression(String.valueOf(getCurrentUserId())));
        }
        query.setPageRequest(pageable);
        solrTemplate.setSolrCore("docs_document");
        ScoredPage<Document> scoredPage = solrTemplate.queryForPage(query, Document.class);
        return scoredPage;
    }

    private Query buildQuery(DocumentVo documentVo) throws ParseException {
        Query query = new SimpleQuery();
        String language = documentVo.getLanguage();
        String title = documentVo.getTitle();
        String description = documentVo.getDescription();
        String subject = documentVo.getSubject();
        Date startCreateDate = documentVo.getStartCreateDate();
        Date endCreteDate = documentVo.getEndCreateDate();
        Date startDocTime = documentVo.getStartDocTime();
        Date endDocTime = documentVo.getEndDocTime();
        String tags = documentVo.getTags();
        String content = documentVo.getContent();
        String summary = documentVo.getSummary();
        String keywords = documentVo.getKeywords();
        String authors = documentVo.getAuthors();
        if (!Strings.isNullOrEmpty(language)) {
            query.addCriteria(new Criteria("language").expression(language));
        }
        if (!Strings.isNullOrEmpty(title)) {
            query.addCriteria(new Criteria("title").expression(title));
        }
        if (!Strings.isNullOrEmpty(description)) {
            query.addCriteria(new Criteria("description").expression(description));
        }
        if (!Strings.isNullOrEmpty(subject)) {
            query.addCriteria(new Criteria("subject").expression(subject));
        }
        if (startCreateDate != null || endCreteDate != null) {
            if (startCreateDate != null && endCreteDate != null) {
                query.addCriteria(new Criteria("createDate").between(startCreateDate, endCreteDate));
            } else if (startCreateDate != null) {
                query.addCriteria(new Criteria("createDate").greaterThan(startCreateDate));
            } else query.addCriteria(new Criteria("createDate").lessThan(endCreteDate));
        }
        if (startDocTime != null || endDocTime != null) {
            if (startDocTime != null && endDocTime != null) {
                query.addCriteria(new Criteria("docTime").between(startDocTime, endDocTime));
            } else if (startDocTime != null) {
                query.addCriteria(new Criteria("docTime").greaterThan(startDocTime));
            } else query.addCriteria(new Criteria("docTime").lessThan(endDocTime));
        }
        if (!Strings.isNullOrEmpty(tags)) {
            query.addCriteria(new Criteria("tags").expression(tags));
        }
        if (!Strings.isNullOrEmpty(content)) {
            query.addCriteria(new Criteria("content").expression(content));
        }
        if (!Strings.isNullOrEmpty(summary)) {
            query.addCriteria(new Criteria("summary").expression(summary));
        }
        if (!Strings.isNullOrEmpty(authors)) {
            query.addCriteria(new Criteria("authors").expression(authors));
        }
        if (!Strings.isNullOrEmpty(keywords)) {
            query.addCriteria(new Criteria("keywords").expression(keywords));
        }
        return query;
    }

    public void delete(List<String> ids) {
        solrTemplate.setSolrCore("docs_document");
        solrTemplate.deleteById(ids);
    }

    public void delete(String id) {
        solrTemplate.setSolrCore("docs_document");
        solrTemplate.deleteById(id);
    }

    /**
     * 取出Shiro中的当前用户Id.
     */
    private Long getCurrentUserId() {
        ShiroDbRealm.ShiroUser user = (ShiroDbRealm.ShiroUser) SecurityUtils.getSubject().getPrincipal();
        if (user == null) {
            return null;
        } else
            return user.id;
    }

    private String getCurrentUserName() {
        ShiroDbRealm.ShiroUser user = (ShiroDbRealm.ShiroUser) SecurityUtils.getSubject().getPrincipal();
        if (user == null)
            return null;
        else return user.loginName;
    }
}
